"""
设计一个培训机构管理系统，有总部、分校，有学员、老师、员工，实现具体如下需求：
1. 有多个课程，课程要有定价
2. 有多个班级，班级跟课程有关联
3. 有多个学生，学生报名班级，交这个班级对应的课程的费用
4. 有多个老师，可以分布在不同校区，上不同班级的课
5. 有多个员工，可以分布在不同校区在总部可以统计各校区的账户余额、员工人数、学员人数
6. 学生可以转校，退学

方法论：
1.定模型，多少个类
    1)找出关键独立名词
        总部
        分校
        学员
        员工
        老师
        课程
        班级
2.定属性
        总部
            名称、地址、电话、网址、财务账户、员工列表、学员列表、发工资、开分校、招人
        分校
            pass
        学员
            姓名、年龄、班级、余额
            上学打卡
            转学？
            交学费
        员工
            姓名、职务、部门、工资
            上班打卡
        老师
            教学
        课程
            名称、价格、大纲
        班级
            校区
            课程
            学期
            学员列表
            转学
            退学
            创建上学记录
            考试
3.定关系
    分校->总部
    学员->班级
    班级->课程
    班级->校区
    老师->班级
    老师->员工
    学员->老师
    员工->校区
4.画结构图，UML模型图：统一建模语言
5.写代码
https://blog.csdn.net/weixin_47872288/article/details/136094957
"""
import datetime
import time


# 总校
class School(object):

    def __init__(self, name, address):
        self.name = name
        self.address = address
        self.balance = 0  # 学校余额
        self.class_list = []  # 班级列表
        self.staff_list = []  # 员工列表
        self.student_list = []  # 学生列表
        self.branch_school_list = []  # 分校列表
        print(f"创建了[{self.name}]校区，地址[{self.address}]。")

    # 入职
    def new_enrollment(self, staff_obj):
        self.staff_list.append(staff_obj)  # 员工入职

    # 统计职工人数
    def count_employee_num(self):
        print(f"校区[{self.name}]职工人数：[{len(self.staff_list)}]")

    # 按总校区统计职工人数
    def count_total_employee_num(self):
        total_employee_num = 0
        for branch_school_obj in self.branch_school_list:
            total_employee_num += len(branch_school_obj.staff_list)  # 先统计所有分校的员工数量
        total_employee_num += len(self.staff_list)  # 加上总校区的员工数量
        print(f"总校区[{self.name}]职工人数：[{total_employee_num}]")

    # 学生入学
    def new_student_enrollment(self, student_obj):
        if student_obj not in self.student_list:  # 一个学生可以在同一个校区报很多个班，但是对于学校来说，只有一个学生
            self.student_list.append(student_obj)

    # 统计学生人数
    def count_student_num(self):
        print(f"校区[{self.name}]学生人数：[{len(self.student_list)}]")

    # 显示校区开设的班级
    def get_school_class(self):
        class_name_s = f"校区[{self.name}]开设的班级有："
        for index, class_obj in enumerate(self.class_list):
            if index == (len(self.class_list) - 1):
                class_name_s += class_obj.class_name
            else:
                class_name_s += f"{class_obj.class_name}，"
        print(class_name_s)

    # 显示校区的余额
    def show_balance(self):
        print(f"[{self.name}]账户余额：{str(self.balance)}")


# 分校
class BranchSchool(School):

    def __init__(self, name, address, headerquater_obj):
        super(BranchSchool, self).__init__(name, address)
        self.headerquater_obj = headerquater_obj  # 总部对象
        self.headerquater_obj.branch_school_list.append(self)  # 建立关联,总校与分校的关联


# 学生
class Student(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.balance = 0 # 学生
        self.class_list = []  # 学生上哪些课程

    # 交学费
    def pay_tuition(self, class_obj):
        # 首先需要添加到班级列表
        self.class_list.append(class_obj)
        class_obj.add_student(self)  # 课程添加学生
        tuition = class_obj.course_obj.price  # 学费=课程的价格
        class_obj.school_obj.balance += tuition  # 交了学费以后，需要修改对应校区的余额
        print(
            f"{datetime.datetime.today()}，校区[{class_obj.school_obj.name}]收到[{self.name}]转账[{tuition}]，交费原因[{class_obj.class_name}]")

    # 退学
    def drop_out_class(self, class_obj):
        print(f"学员[{self.name}]从[{class_obj.class_name}]退学了...")
        class_obj.student_list.remove(self)  # 先将同学在班级名单里删除
        # 退还对应班级学费
        class_obj.school_obj.balance -= class_obj.course_obj.price
        self.class_list.remove(class_obj)  # 同时删除自己的班级列表

    # 转校
    def change_class(self, new_class_obj):
        # 先退费
        for old_class_obj in self.class_list:
            self.drop_out_class(old_class_obj)

        # 再入学
        self.pay_tuition(new_class_obj)

    def get_class_list(self):
        class_name_s = f"学生[{self.name}]参与的课程有："
        for index, class_obj in enumerate(self.class_list):
            if index == (len(self.class_list) - 1):
                class_name_s += class_obj.class_name
            else:
                class_name_s += f"{class_obj.class_name}，"
        print(class_name_s)


# 员工
class Staff(object):

    def __init__(self, name, age, salary, position, dept, school_obj):
        self.name = name
        self.age = age
        self.salary = salary
        self.position = position
        self.dept = dept
        self.school_obj = school_obj
        self.school_obj.new_enrollment(self)
        print(f"创建了员工[{self.name}]，职位[{self.position}],部门[{self.dept}],所属校区[{self.school_obj.name}]。")


# 老师
class Teacher(Staff):

    # 老师默认
    def __init__(self, name, age, salary, school_obj):
        self.position = "讲师"
        self.dept = "教务部"
        super(Teacher, self).__init__(name, age, salary, self.position, self.dept, school_obj)
        self.class_list = []

    # 老师创建授课记录
    def create_class_record(self, *args):
        self.class_list = args
        class_name_s = f"老师[{self.name}]负责班级："
        for index, class_obj in enumerate(self.class_list):
            if index == (len(self.class_list) - 1):
                class_name_s += class_obj.class_name
            else:
                class_name_s += f"{class_obj.class_name}，"
        print(class_name_s)


# 课程
class Course(object):

    # 有多个课程，课程要有定价
    def __init__(self, name, price):
        self.name = name
        self.price = price
        print(f"创建了课程[{self.name}]，价格[{str(self.price)}]。")


# 有多个班级，班级跟课程有关联
# 班级
class Class(object):

    def __init__(self, school_obj, course_obj, class_num):
        self.school_obj = school_obj
        self.course_obj = course_obj
        self.class_num = class_num
        self.class_name = self.create_class()  # 班级名称
        self.student_list = []  # 学生列表
        print(f"创建了班级[{self.class_name}]")

    # 创建班级
    def create_class(self):
        self.school_obj.class_list.append(self)  # 同时将班级加到对应的学校中
        return f"{self.school_obj.name}-{self.course_obj.name}-s{self.class_num}期"

    # 添加学生
    def add_student(self, student_obj):
        self.student_list.append(student_obj)  # 将学生添加到班级中
        self.school_obj.new_student_enrollment(student_obj)  # 学生入学

    def get_student_list(self):
        student_name_s = f"课程[{self.class_name}]参与的学生有："
        for index, student_obj in enumerate(self.student_list):
            if index == (len(self.student_list) - 1):
                student_name_s += student_obj.name
            else:
                student_name_s += f"{student_obj.name}，"
        print(student_name_s)


if __name__ == "__main__":
    # 校区初始化
    s_beijing = School("路飞总部（北京校区）", "北京市昌平区回龙观东大街338号1号院腾讯众创空间 A-3F")
    bs_xian = BranchSchool("西安校区", "陕西省西安市高新区万达one 1号楼 18F", s_beijing)
    bs_shenzhen = BranchSchool("深圳校区", "深圳龙岗区坂田五和大道 4004", s_beijing)

    # 初始化课程
    python_op = Course("python全栈开发", 230000)
    python_data_analyze = Course("python数据分析", 12000)
    linux_cloud_cal = Course("linux云计算开发", 9000)
    go_op = Course("Go语言开发", 7000)

    # 员工入职
    alex = Staff("Alex", 42, 2, "CEO", "总经办", s_beijing)
    zhouxiaoyue = Staff("周小月", 30, 6000, "财务", "财务部", s_beijing)
    jinjiaodawang = Teacher("金角大王", 30, 6000, s_beijing)
    yinjiaodawang = Teacher("银角大王", 30, 6000, bs_xian)
    qiaofu = Teacher("樵夫", 30, 6000, bs_shenzhen)
    lucky = Teacher("Lucky", 30, 6000, s_beijing)
    yuanhao = Teacher("苑昊", 30, 6000, bs_xian)

    # 统计员工人数
    s_beijing.count_employee_num()
    bs_xian.count_employee_num()
    bs_shenzhen.count_employee_num()
    s_beijing.count_total_employee_num()

    # 初始化班级
    c_s_beijing_python_op_21 = Class(s_beijing, python_op, 21)
    c_s_beijing_python_data_analyze_19 = Class(s_beijing, python_data_analyze, 19)
    c_bs_xian_linux_cloud_cal_10 = Class(bs_xian, linux_cloud_cal, 10)
    c_bs_shenzhen_go_op_5 = Class(bs_shenzhen, go_op, 5)

    # 各校区的班级
    s_beijing.get_school_class()
    bs_xian.get_school_class()
    bs_shenzhen.get_school_class()

    # 老师上不同班级的课
    jinjiaodawang.create_class_record(c_s_beijing_python_op_21, c_s_beijing_python_data_analyze_19)
    yuanhao.create_class_record(c_s_beijing_python_op_21, c_bs_shenzhen_go_op_5)
    yinjiaodawang.create_class_record(c_s_beijing_python_data_analyze_19, c_bs_xian_linux_cloud_cal_10)
    qiaofu.create_class_record(c_bs_shenzhen_go_op_5, c_s_beijing_python_op_21)
    lucky.create_class_record(c_s_beijing_python_op_21)

    # 学生报名课程
    black_girl = Student("黑姑娘")
    black_girl.pay_tuition(c_s_beijing_python_op_21)
    black_girl.get_class_list()
    black_girl.pay_tuition(c_s_beijing_python_data_analyze_19)
    black_girl.get_class_list()
    lao_baby = Student("老baby")
    lao_baby.pay_tuition(c_bs_shenzhen_go_op_5)
    lao_baby.get_class_list()
    xiao_baby = Student("小baby")
    xiao_baby.pay_tuition(c_bs_shenzhen_go_op_5)
    xiao_baby.get_class_list()
    man_man = Student("漫漫")
    man_man.pay_tuition(c_bs_xian_linux_cloud_cal_10)
    man_man.get_class_list()

    # 打印各校区学生数量
    s_beijing.count_student_num()
    bs_xian.count_student_num()
    bs_shenzhen.count_student_num()

    # 打印各校区的余额
    s_beijing.show_balance()
    bs_xian.show_balance()
    bs_shenzhen.show_balance()

    # 打印各班级的学生
    c_s_beijing_python_op_21.get_student_list()
    c_s_beijing_python_data_analyze_19.get_student_list()
    c_bs_shenzhen_go_op_5.get_student_list()
    c_bs_xian_linux_cloud_cal_10.get_student_list()

    # 退学
    lao_baby.drop_out_class(c_bs_shenzhen_go_op_5)
    lao_baby.get_class_list()

    # 打印各校区学生数量
    s_beijing.count_student_num()
    bs_xian.count_student_num()
    bs_shenzhen.count_student_num()

    # 打印各校区的余额
    s_beijing.show_balance()
    bs_xian.show_balance()
    bs_shenzhen.show_balance()

    # 打印各班级的学生
    c_s_beijing_python_op_21.get_student_list()
    c_s_beijing_python_data_analyze_19.get_student_list()
    c_bs_shenzhen_go_op_5.get_student_list()
    c_bs_xian_linux_cloud_cal_10.get_student_list()

    # 转学
    black_girl.change_class(c_bs_shenzhen_go_op_5)

    # 打印各校区学生数量
    s_beijing.count_student_num()
    bs_xian.count_student_num()
    bs_shenzhen.count_student_num()

    # 打印各校区的余额
    s_beijing.show_balance()
    bs_xian.show_balance()
    bs_shenzhen.show_balance()

    # 打印各班级的学生
    c_s_beijing_python_op_21.get_student_list()
    c_s_beijing_python_data_analyze_19.get_student_list()
    c_bs_shenzhen_go_op_5.get_student_list()
    c_bs_xian_linux_cloud_cal_10.get_student_list()
